> ## Documentation Index
> Fetch the complete documentation index at: https://sequence-0fb8d9e6-api_docs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Wallet Configuration

> The Sequence wallet configuration includes a threshold and a list of signers with their weights.

Every Sequence wallet has a configuration defined by a threshold and a list of signers with their corresponding weights.

## Configuration layout

| Name      | Type       | Range                      | Description                                                                         |
| --------- | ---------- | -------------------------- | ----------------------------------------------------------------------------------- |
| Threshold | `uint16`   | 1 - 65535                  | Required combined total "weight" of signers for a signature to be considered valid. |
| Signers   | `signer[]` | unlimited - bounded by gas | List of signers that with their corresponding "weight"s.                            |

### Signer layout

| Name      | Type        | Range   | Description                                                                                       |
| --------- | ----------- | ------- | ------------------------------------------------------------------------------------------------- |
| "weight"  | `uint8`     | 0 - 255 | "weight" of every signature of the signer.                                                        |
| "address" | `"address"` | --      | "address" of the signer, it may be an EOA or another smart contract wallet with EIP-1271 support. |

#### Example

```json theme={null}
{
  "threshold": 5,
  "signers": [
    {
      "address": "0x4fbf69aa2a75f9942a768dc8da7804ec965f7bea",
      "weight": 2
    },
    {
      "address": "0x596af90cecdbf9a768886e771178fd5561dd27ab",
      "weight": 3
    },
    {
      "address": "0x6192e0fdcd868b3de01c7fbc0ad98baebd7330c1",
      "weight": 2
    },
    {
      "address": "0xec9a7204a43d3f4a82c84fde92d25bfc9110981e",
      "weight": 1
    }
  ]
}
```

This example has a threshold of 5 and 4 signers.

#### The valid combinations of signers are:

```
- 0x4fbf69aa2a75f9942a768dc8da7804ec965f7bea & 0x596af90cecdbf9a768886e771178fd5561dd27ab - combined weight of 2 + 3 = 5
- 0x6192e0fdcd868b3de01c7fbc0ad98baebd7330c1 & 0x596af90cecdbf9a768886e771178fd5561dd27ab - combined weight of 2 + 3 = 5
- 0x4fbf69aa2a75f9942a768dc8da7804ec965f7bea, 0x6192e0fdcd868b3de01c7fbc0ad98baebd7330c1 & 0xec9a7204a43d3f4a82c84fde92d25bfc9110981e - combined weight of 2 + 2 + 1 = 5
```

Any combination of signers with a combined weight under the threshold is considered invalid; any additional signers above the threshold are ignored.

### Configuration hash - ImageHash

The configuration is never stored directly on the contract, but instead is hashed and checked against every time a signature is validated. This allows the wallet contracts to reduce the usage of storage and therefore the gas cost.

Wallets that never have been updated don't store the `imageHash` directly, instead the `imageHash` is used as the `salt` during the contract creation, and signatures are validated against the address of the wallet.

#### Compute image hash

<CodeGroup>
  ```solidity twoslash solidity theme={null}
    keccak256(abi.encode( uint8 weight_1, address signer_1,
    keccak256(abi.encode( uint8 weight_2, address signer_2,
    keccak256(abi.encode( uint8 weight_3, address signer_3,
    keccak256(abi.encode( uint256 threshold )) )) )) )) 
  ```

  ```js twoslash TypeScript theme={null}
    let tmp = ethers.solidityPackedKeccak256(['uint256'], [configuration.threshold])

    for (const signer of configuration.signers) {
      tmp = ethers.solidityPackedKeccak256(
        AbiCoder.defaultAbiCoder().encode(
          ['bytes32', 'uint8', 'address'],
          [tmp, signer.weight, signer.address]
        )
      )
    }

    const imageHash = tmp
  ```
</CodeGroup>

## Initial wallet configuration

The initial wallet configuration determines the address of the wallet, subsequent updates don't change the address.

The wallet address can be computed using the `imageHash`, the `factory` and `mainModule` of the wallet.

#### Compute wallet address

```js theme={null}
// The code of the wallet proxy contract
const WalletProxyBytecode =
"0x603a600e3d39601a805130553df3363d3d373d3d3d363d30545af43d82803e903d91601857fd5bf3";

// These values are defined by the wallet context
// they must be known in order to validate the counter-factual wallet imageHash
const factory = "0xf9D09D634Fb818b05149329C1dcCFAeA53639d96";
const mainModule = "0xd01F11855bCcb95f88D7A48492F66410d4637313";

// Append the `mainModule` to the `WalletProxyBytecode`
// this completed the creation code of the proxy contract
// used for computing the wallet address as defined by the CREATE2 opcode
const codeHash = ethers.solidityPackedKeccak256(
ethers.solidityPackedKeccak256(
["bytes", "bytes32"],
[WalletContractBytecode, ethers.hexZeroPad(mainModule, 32)]
)
);

// Compute the wallet address
const hash = ethers.solidityPackedKeccak256(
ethers.solidityPackedKeccak256(
["bytes1", "address", "bytes32", "bytes32"],
["0xff", factory, salt, codeHash]
)
);

const address = ethers.getAddress(ethers.dataSlice(hash, 12));
```
